// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.iso;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import zombie.core.properties.PropertyContainer;
import zombie.iso.SpriteDetails.IsoFlagType;
import zombie.iso.SpriteDetails.IsoObjectType;
import zombie.iso.areas.IsoRoom;
import zombie.iso.sprite.IsoSprite;

public final class IsoRoofFixer {
    private static final boolean PER_ROOM_MODE = true;
    private static final int MAX_Z = 8;
    private static final int SCAN_RANGE = 3;
    private static final boolean ALWAYS_INVIS_FLOORS = false;
    private static boolean roofTileGlassCacheDirty = true;
    private static boolean roofTileIsGlass = false;
    private static IsoSprite roofTileCache;
    private static int roofTilePlaceFloorIndexCache = 0;
    private static String invisFloor = "invisible_01_0";
    private static Map<Integer, String> roofGroups = new HashMap();
    private static IsoRoofFixer.PlaceFloorInfo[] placeFloorInfos = new IsoRoofFixer.PlaceFloorInfo[10000];
    private static int floorInfoIndex = 0;
    private static IsoGridSquare[] sqCache;
    private static IsoRoom workingRoom;
    private static int[] interiorAirSpaces;
    private static final int I_UNCHECKED = 0;
    private static final int I_TRUE = 1;
    private static final int I_FALSE = 2;

    private static void ensureCapacityFloorInfos() {
        if (floorInfoIndex == placeFloorInfos.length) {
            IsoRoofFixer.PlaceFloorInfo[] placeFloorInfo = placeFloorInfos;
            placeFloorInfos = new IsoRoofFixer.PlaceFloorInfo[placeFloorInfos.length + 400];
            System.arraycopy(placeFloorInfo, 0, placeFloorInfos, 0, placeFloorInfo.length);
        }
    }

    private static void setRoofTileCache(IsoObject isoObject) {
        IsoSprite isoSprite = isoObject != null ? isoObject.sprite : null;
        if (roofTileCache != isoSprite) {
            roofTileCache = isoSprite;
            roofTilePlaceFloorIndexCache = 0;
            if (isoSprite != null && isoSprite.getProperties() != null && isoSprite.getProperties().Val("RoofGroup") != null) {
                try {
                    int _int = Integer.parseInt(isoSprite.getProperties().Val("RoofGroup"));
                    if (roofGroups.containsKey(_int)) {
                        roofTilePlaceFloorIndexCache = _int;
                    }
                } catch (Exception exception) {
                }
            }

            roofTileGlassCacheDirty = true;
        }
    }

    private static boolean isRoofTileCacheGlass() {
        if (roofTileGlassCacheDirty) {
            roofTileIsGlass = false;
            if (roofTileCache != null) {
                PropertyContainer propertyContainer = roofTileCache.getProperties();
                if (propertyContainer != null) {
                    String string = propertyContainer.Val("Material");
                    roofTileIsGlass = string != null && string.equalsIgnoreCase("glass");
                }
            }

            roofTileGlassCacheDirty = false;
        }

        return roofTileIsGlass;
    }

    public static void FixRoofsAt(IsoGridSquare current) {
        try {
            FixRoofsPerRoomAt(current);
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    private static void FixRoofsPerRoomAt(IsoGridSquare isoGridSquare0) {
        floorInfoIndex = 0;
        if (isoGridSquare0.getZ() > 0 && !isoGridSquare0.TreatAsSolidFloor() && isoGridSquare0.getRoom() == null) {
            IsoRoom isoRoom = getRoomBelow(isoGridSquare0);
            if (isoRoom != null && !isoRoom.def.isRoofFixed()) {
                resetInteriorSpaceCache();
                workingRoom = isoRoom;
                ArrayList arrayList = isoRoom.getSquares();

                for (int int0 = 0; int0 < arrayList.size(); int0++) {
                    IsoGridSquare isoGridSquare1 = (IsoGridSquare)arrayList.get(int0);
                    IsoGridSquare isoGridSquare2 = getRoofFloorForColumn(isoGridSquare1);
                    if (isoGridSquare2 != null) {
                        ensureCapacityFloorInfos();
                        placeFloorInfos[floorInfoIndex++].set(isoGridSquare2, roofTilePlaceFloorIndexCache);
                    }
                }

                isoRoom.def.setRoofFixed(true);
            }
        }

        for (int int1 = 0; int1 < floorInfoIndex; int1++) {
            placeFloorInfos[int1].square.addFloor((String)roofGroups.get(placeFloorInfos[int1].floorType));
        }
    }

    private static void clearSqCache() {
        for (int _int = 0; _int < sqCache.length; _int++) {
            sqCache[_int] = null;
        }
    }

    private static IsoGridSquare getRoofFloorForColumn(IsoGridSquare isoGridSquare0) {
        if (isoGridSquare0 == null) {
            return null;
        } else {
            IsoCell isoCell = IsoCell.getInstance();
            int int0 = 0;
            boolean _boolean = false;
            int int1 = 7;

            while (true) {
                label163: {
                    if (int1 >= isoGridSquare0.getZ() + 1) {
                        IsoGridSquare isoGridSquare1 = isoCell.getGridSquare(isoGridSquare0.x, isoGridSquare0.y, int1);
                        if (isoGridSquare1 == null) {
                            if (int1 == isoGridSquare0.getZ() + 1 && int1 > 0 && !isStairsBelow(isoGridSquare0.x, isoGridSquare0.y, int1)) {
                                isoGridSquare1 = IsoGridSquare.getNew(isoCell, null, isoGridSquare0.x, isoGridSquare0.y, int1);
                                isoCell.ConnectNewSquare(isoGridSquare1, false);
                                isoGridSquare1.EnsureSurroundNotNull();
                                isoGridSquare1.RecalcAllWithNeighbours(true);
                                sqCache[int0++] = isoGridSquare1;
                            }

                            _boolean = true;
                            break label163;
                        }

                        if (isoGridSquare1.TreatAsSolidFloor()) {
                            if (isoGridSquare1.getRoom() == null) {
                                IsoObject isoObject0 = isoGridSquare1.getFloor();
                                if (isoObject0 == null || !isObjectRoof(isoObject0) || isoObject0.getProperties() == null) {
                                    break;
                                }

                                PropertyContainer propertyContainer = isoObject0.getProperties();
                                if (propertyContainer.Is(IsoFlagType.FloorHeightOneThird) || propertyContainer.Is(IsoFlagType.FloorHeightTwoThirds)) {
                                    break;
                                }

                                IsoGridSquare isoGridSquare2 = isoCell.getGridSquare(isoGridSquare0.x, isoGridSquare0.y, int1 - 1);
                                if (isoGridSquare2 == null || isoGridSquare2.getRoom() != null) {
                                    break;
                                }

                                _boolean = false;
                                break label163;
                            }

                            if (_boolean) {
                                isoGridSquare1 = IsoGridSquare.getNew(isoCell, null, isoGridSquare0.x, isoGridSquare0.y, int1 + 1);
                                isoCell.ConnectNewSquare(isoGridSquare1, false);
                                isoGridSquare1.EnsureSurroundNotNull();
                                isoGridSquare1.RecalcAllWithNeighbours(true);
                                sqCache[int0++] = isoGridSquare1;
                            }
                        } else if (!isoGridSquare1.HasStairsBelow()) {
                            _boolean = false;
                            sqCache[int0++] = isoGridSquare1;
                            break label163;
                        }
                    }

                    if (int0 == 0) {
                        return null;
                    }

                    for (int int2 = 0; int2 < int0; int2++) {
                        IsoGridSquare isoGridSquare3 = sqCache[int2];
                        if (isoGridSquare3.getRoom() == null && isInteriorAirSpace(isoGridSquare3.getX(), isoGridSquare3.getY(), isoGridSquare3.getZ())) {
                            return null;
                        }

                        if (isRoofAt(isoGridSquare3, true)) {
                            return isoGridSquare3;
                        }

                        for (int int3 = isoGridSquare3.x - 3; int3 <= isoGridSquare3.x + 3; int3++) {
                            for (int int4 = isoGridSquare3.y - 3; int4 <= isoGridSquare3.y + 3; int4++) {
                                if (int3 != isoGridSquare3.x || int4 != isoGridSquare3.y) {
                                    IsoGridSquare isoGridSquare4 = isoCell.getGridSquare(int3, int4, isoGridSquare3.z);
                                    if (isoGridSquare4 != null) {
                                        for (int int5 = 0; int5 < isoGridSquare4.getObjects().size(); int5++) {
                                            IsoObject isoObject1 = isoGridSquare4.getObjects().get(int5);
                                            if (isObjectRoofNonFlat(isoObject1)) {
                                                setRoofTileCache(isoObject1);
                                                return isoGridSquare3;
                                            }
                                        }

                                        IsoGridSquare isoGridSquare5 = isoCell.getGridSquare(isoGridSquare4.x, isoGridSquare4.y, isoGridSquare4.z + 1);
                                        if (isoGridSquare5 != null && isoGridSquare5.getObjects().size() > 0) {
                                            for (int int6 = 0; int6 < isoGridSquare5.getObjects().size(); int6++) {
                                                IsoObject isoObject2 = isoGridSquare5.getObjects().get(int6);
                                                if (isObjectRoofFlatFloor(isoObject2)) {
                                                    setRoofTileCache(isoObject2);
                                                    return isoGridSquare3;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    return null;
                }

                int1--;
            }

            return null;
        }
    }

    private static void FixRoofsPerTileAt(IsoGridSquare isoGridSquare) {
        if (isoGridSquare.getZ() > 0
            && !isoGridSquare.TreatAsSolidFloor()
            && isoGridSquare.getRoom() == null
            && hasRoomBelow(isoGridSquare)
            && (isRoofAt(isoGridSquare, true) || scanIsRoofAt(isoGridSquare, true))) {
            if (isRoofTileCacheGlass()) {
                isoGridSquare.addFloor(invisFloor);
            } else {
                isoGridSquare.addFloor("carpentry_02_58");
            }
        }
    }

    private static boolean scanIsRoofAt(IsoGridSquare isoGridSquare0, boolean _boolean) {
        if (isoGridSquare0 == null) {
            return false;
        } else {
            for (int int0 = isoGridSquare0.x - 3; int0 <= isoGridSquare0.x + 3; int0++) {
                for (int int1 = isoGridSquare0.y - 3; int1 <= isoGridSquare0.y + 3; int1++) {
                    if (int0 != isoGridSquare0.x || int1 != isoGridSquare0.y) {
                        IsoGridSquare isoGridSquare1 = isoGridSquare0.getCell().getGridSquare(int0, int1, isoGridSquare0.z);
                        if (isoGridSquare1 != null && isRoofAt(isoGridSquare1, _boolean)) {
                            return true;
                        }
                    }
                }
            }

            return false;
        }
    }

    private static boolean isRoofAt(IsoGridSquare isoGridSquare0, boolean _boolean) {
        if (isoGridSquare0 == null) {
            return false;
        } else {
            for (int int0 = 0; int0 < isoGridSquare0.getObjects().size(); int0++) {
                IsoObject isoObject0 = isoGridSquare0.getObjects().get(int0);
                if (isObjectRoofNonFlat(isoObject0)) {
                    setRoofTileCache(isoObject0);
                    return true;
                }
            }

            if (_boolean) {
                IsoGridSquare isoGridSquare1 = isoGridSquare0.getCell().getGridSquare(isoGridSquare0.x, isoGridSquare0.y, isoGridSquare0.z + 1);
                if (isoGridSquare1 != null && isoGridSquare1.getObjects().size() > 0) {
                    for (int int1 = 0; int1 < isoGridSquare1.getObjects().size(); int1++) {
                        IsoObject isoObject1 = isoGridSquare1.getObjects().get(int1);
                        if (isObjectRoofFlatFloor(isoObject1)) {
                            setRoofTileCache(isoObject1);
                            return true;
                        }
                    }
                }
            }

            return false;
        }
    }

    private static boolean isObjectRoof(IsoObject isoObject) {
        return isoObject != null
            && (
                isoObject.getType() == IsoObjectType.WestRoofT
                    || isoObject.getType() == IsoObjectType.WestRoofB
                    || isoObject.getType() == IsoObjectType.WestRoofM
            );
    }

    private static boolean isObjectRoofNonFlat(IsoObject isoObject) {
        if (isObjectRoof(isoObject)) {
            PropertyContainer propertyContainer = isoObject.getProperties();
            if (propertyContainer != null) {
                return !propertyContainer.Is(IsoFlagType.solidfloor)
                    || propertyContainer.Is(IsoFlagType.FloorHeightOneThird)
                    || propertyContainer.Is(IsoFlagType.FloorHeightTwoThirds);
            }
        }

        return false;
    }

    private static boolean isObjectRoofFlatFloor(IsoObject isoObject) {
        if (isObjectRoof(isoObject)) {
            PropertyContainer propertyContainer = isoObject.getProperties();
            if (propertyContainer != null && propertyContainer.Is(IsoFlagType.solidfloor)) {
                return !propertyContainer.Is(IsoFlagType.FloorHeightOneThird) && !propertyContainer.Is(IsoFlagType.FloorHeightTwoThirds);
            }
        }

        return false;
    }

    private static boolean hasRoomBelow(IsoGridSquare isoGridSquare) {
        return getRoomBelow(isoGridSquare) != null;
    }

    private static IsoRoom getRoomBelow(IsoGridSquare isoGridSquare0) {
        if (isoGridSquare0 == null) {
            return null;
        } else {
            for (int _int = isoGridSquare0.z - 1; _int >= 0; _int--) {
                IsoGridSquare isoGridSquare1 = isoGridSquare0.getCell().getGridSquare(isoGridSquare0.x, isoGridSquare0.y, _int);
                if (isoGridSquare1 != null) {
                    if (isoGridSquare1.TreatAsSolidFloor() && isoGridSquare1.getRoom() == null) {
                        return null;
                    }

                    if (isoGridSquare1.getRoom() != null) {
                        return isoGridSquare1.getRoom();
                    }
                }
            }

            return null;
        }
    }

    private static boolean isStairsBelow(int int1, int int2, int int0) {
        if (int0 == 0) {
            return false;
        } else {
            IsoCell isoCell = IsoCell.getInstance();
            IsoGridSquare isoGridSquare = isoCell.getGridSquare(int1, int2, int0 - 1);
            return isoGridSquare != null && isoGridSquare.HasStairs();
        }
    }

    private static void resetInteriorSpaceCache() {
        for (int _int = 0; _int < interiorAirSpaces.length; _int++) {
            interiorAirSpaces[_int] = 0;
        }
    }

    private static boolean isInteriorAirSpace(int var0, int var1, int int0) {
        if (interiorAirSpaces[int0] != 0) {
            return interiorAirSpaces[int0] == 1;
        } else {
            ArrayList arrayList = workingRoom.getSquares();
            boolean _boolean = false;
            if (arrayList.size() > 0 && int0 > ((IsoGridSquare)arrayList.get(0)).getZ()) {
                for (int int1 = 0; int1 < workingRoom.rects.size(); int1++) {
                    RoomDef.RoomRect roomRect = (RoomDef.RoomRect)workingRoom.rects.get(int1);

                    for (int int2 = roomRect.getX(); int2 < roomRect.getX2(); int2++) {
                        if (hasRailing(int2, roomRect.getY(), int0, IsoDirections.N) || hasRailing(int2, roomRect.getY2() - 1, int0, IsoDirections.S)) {
                            _boolean = true;
                            break;
                        }
                    }

                    if (_boolean) {
                        break;
                    }

                    for (int int3 = roomRect.getY(); int3 < roomRect.getY2(); int3++) {
                        if (hasRailing(roomRect.getX(), int3, int0, IsoDirections.W) || hasRailing(roomRect.getX2() - 1, int3, int0, IsoDirections.E)) {
                            _boolean = true;
                            break;
                        }
                    }
                }
            }

            interiorAirSpaces[int0] = _boolean ? 1 : 2;
            return _boolean;
        }
    }

    private static boolean hasRailing(int int0, int int1, int int2, IsoDirections isoDirections) {
        IsoCell isoCell = IsoCell.getInstance();
        IsoGridSquare isoGridSquare = isoCell.getGridSquare(int0, int1, int2);
        if (isoGridSquare == null) {
            return false;
        } else {
            switch (isoDirections) {
                case N:
                    return isoGridSquare.isHoppableTo(isoCell.getGridSquare(int0, int1 - 1, int2));
                case E:
                    return isoGridSquare.isHoppableTo(isoCell.getGridSquare(int0 + 1, int1, int2));
                case S:
                    return isoGridSquare.isHoppableTo(isoCell.getGridSquare(int0, int1 + 1, int2));
                case W:
                    return isoGridSquare.isHoppableTo(isoCell.getGridSquare(int0 - 1, int1, int2));
                default:
                    return false;
            }
        }
    }

    static {
        roofGroups.put(0, "carpentry_02_57");
        roofGroups.put(1, "roofs_01_22");
        roofGroups.put(2, "roofs_01_54");
        roofGroups.put(3, "roofs_02_22");
        roofGroups.put(4, invisFloor);
        roofGroups.put(5, "roofs_03_22");
        roofGroups.put(6, "roofs_03_54");
        roofGroups.put(7, "roofs_04_22");
        roofGroups.put(8, "roofs_04_54");
        roofGroups.put(9, "roofs_05_22");
        roofGroups.put(10, "roofs_05_54");

        for (int _int = 0; _int < placeFloorInfos.length; _int++) {
            placeFloorInfos[_int] = new IsoRoofFixer.PlaceFloorInfo();
        }

        sqCache = new IsoGridSquare[8];
        interiorAirSpaces = new int[8];
    }

    private static final class PlaceFloorInfo {
        private IsoGridSquare square;
        private int floorType;

        private void set(IsoGridSquare isoGridSquare, int _int) {
            this.square = isoGridSquare;
            this.floorType = _int;
        }
    }
}
